home *** CD-ROM | disk | FTP | other *** search
/ No Fragments Archive 12: Textmags & Docs / nf_archive_12.iso / MAGS / SOURCES / ATARI_SRC.ZIP / atari source / HDX_BACK / HDXPCH / GETSTART.C < prev    next >
Encoding:
C/C++ Source or Header  |  2001-02-09  |  9.3 KB  |  399 lines

  1. /* _______________
  2. ** getstart, fatck - get starting cluster, FAT consistency check
  3. ** atari corp    (1 March 1988)  asm
  4. **
  5. ** see GETSTART(3) manual pages
  6. **
  7. ** Fatck and support algorithms are courtesy Derek Mui.
  8. **
  9. ** $Header$
  10. ** $Source$
  11. ** $Author$
  12. **
  13. ** $Revision$
  14. ** $Date$
  15. ** $State$
  16. ** $Locker$
  17. ** $Log$
  18. */
  19.  
  20.  
  21.  
  22. # include    <osbind.h>
  23. # include    "getstart.h"
  24.  
  25. # define    OSIZE    (32767)        /* orphan list size in words */
  26. # define    ROOT    (0)        /* root directory dummy cluster */
  27. # define    EOFAT    (0xffff)    /* end of file allocation chain */
  28.  
  29. BPB *bp;                /* pointer to device BPB */
  30. char *fat1buf;                /* first FAT buffer */
  31. char *fat2buf;                /* second FAT buffer */
  32. char *rootbuf;                /* root directory buffer */
  33. char *clusbuf;                /* general-purpose cluster buffer */
  34.  
  35.  
  36.  
  37. /*
  38. ** Get starting cluster.
  39. */
  40.  
  41. GSINFO *getstart (orphans, clusno, devno)
  42. register int *orphans;
  43. register int clusno, devno;
  44. {
  45.    static GSINFO info;
  46.    register unsigned i, fatlen;
  47.  
  48.    if ((long)orphans <= 0L)
  49.       return ((GSINFO *)GOOFY);        /* FAT not validated by fatck */
  50.  
  51.    if (!allobuf (devno))        /* cache for FATs and root directory */
  52.    {
  53.       freebuf ();
  54.       return (GFAIL);
  55.    }
  56.    if (!readfat (devno))        /* get first and second FATs */
  57.    {
  58.       freebuf ();
  59.       return (GFAIL);
  60.    }
  61.    if (!readroo (devno))        /* get root directory */
  62.    {
  63.       freebuf ();
  64.       return (GFAIL);
  65.    }
  66.  
  67.    if (!nextcl (clusno))
  68.    {
  69.       freebuf ();
  70.       return ((GSINFO *)GALLO);        /* current cluster not allocated */
  71.    }
  72.    if (bsearch ((orphans+1), *orphans, clusno))
  73.    {
  74.       freebuf ();
  75.       return ((GSINFO *)GORPH);        /* orphan in FAT allocation chain */
  76.    }
  77.  
  78.    info.gs_count = 1;            /* backtrack file allocation chain */
  79.    info.gs_prev = 0;
  80.    fatlen = bp->numcl + 2;
  81.    while (1)                /* look up and down FAT */
  82.    {
  83.       for (i = clusno - 1; i >= 2; i--)
  84.          if (nextcl (i) == clusno)
  85.          {
  86.             clusno = i;
  87.             if (bsearch ((orphans+1), *orphans, clusno))
  88.             {
  89.                freebuf ();
  90.                return ((GSINFO *)GORPH);
  91.             }
  92.             info.gs_count++;
  93.             if (!info.gs_prev)
  94.                info.gs_prev = clusno;
  95.          }
  96.       for (i = clusno + 1; i <= fatlen; i++)
  97.          if (nextcl (i) == clusno)
  98.          {
  99.             clusno = i;
  100.             if (bsearch ((orphans+1), *orphans, clusno))
  101.             {
  102.                freebuf ();
  103.                return ((GSINFO *)GORPH);
  104.             }
  105.             info.gs_count++;
  106.             if (!info.gs_prev)
  107.                info.gs_prev = clusno;
  108.             break;
  109.          }
  110.       if (i > fatlen)
  111.          break;
  112.    }
  113.    info.gs_head = clusno;
  114.  
  115.    branch (devno, ROOT, clusno, &info);    /* find starting cluster */
  116.  
  117.    freebuf ();
  118.    return (&info);
  119. }
  120.  
  121.  
  122.  
  123. /*
  124. ** FAT consistency check.
  125. */
  126.  
  127. int *fatck (devno)
  128. register int devno;
  129. {
  130.    static int olist[OSIZE];
  131.    register unsigned i, fatlen;
  132.  
  133.    if (!allobuf (devno))        /* cache for FATs and root directory */
  134.    {
  135.       freebuf ();
  136.       return (FFAIL);
  137.    }
  138.    if (!readfat (devno))        /* get first and second FATs */
  139.    {
  140.       freebuf ();
  141.       return ((int *)FFATS);
  142.    }
  143.    if (!readroo (devno))        /* get root directory */
  144.    {
  145.       freebuf ();
  146.       return ((int *)FROOT);
  147.    }
  148.  
  149.    fatlen = bp->fsiz * bp->recsiz;    /* compare first and second FATs */
  150.    for (i = 0; i < fatlen; i += sizeof(long))
  151.       if (*((long *)(fat1buf+i)) != *((long *)(fat2buf+i)))
  152.       {
  153.          freebuf ();
  154.          return ((int *)FCONF);        /* conflicting FAT entry */
  155.       }
  156.  
  157.    fatlen = bp->numcl + 2;        /* zero tallies */
  158.    for (i = 2; i <= fatlen; i += sizeof(long))
  159.       *((long *)(fat2buf+i)) = 0L;
  160.  
  161.    branch (devno, ROOT, 0, 0L);        /* traverse entire directory tree */
  162.  
  163.    olist[0] = 0;            /* check tallies, build orphan list */
  164.    for (i = 2; i <= fatlen; i++)
  165.    {
  166.       if (*(fat2buf+i) > 1)
  167.       {
  168.          freebuf ();
  169.          return ((int *)FAMBI);        /* ambiguous FAT entry reference */
  170.       }
  171.       if (!(*(fat2buf+i)) && nextcl (i))
  172.          olist[++olist[0]] = i;
  173.    }
  174.  
  175.    freebuf ();
  176.    return (&olist[0]);
  177. }
  178.  
  179.  
  180.  
  181. /*
  182. ** Miscellaneous support functions.
  183. */
  184.  
  185. int allobuf (dev)            /* allocate memory for buffers */
  186. int dev;
  187. {
  188.    if (!(bp = (BPB *)Getbpb (dev)))
  189.       return (0);
  190.    if (!(fat1buf = (char *)Malloc ((long)bp->fsiz * (long)bp->recsiz)))
  191.       return (0);
  192.    if (!(fat2buf = (char *)Malloc ((long)bp->fsiz * (long)bp->recsiz)))
  193.       return (0);
  194.    if (!(rootbuf = (char *)Malloc ((long)bp->rdlen * (long)bp->recsiz)))
  195.       return (0);
  196.    return ((int)(clusbuf = (char *)Malloc ((long)bp->clsiz
  197.       * (long)bp->recsiz)));
  198. }
  199.  
  200. int readfat (dev)            /* read first and second FATs */
  201. int dev;
  202. {
  203.    if (Rwabs (0, fat1buf, bp->fsiz, bp->fatrec - bp->fsiz, dev))
  204.       return (0);
  205.    return (!Rwabs (0, fat2buf, bp->fsiz, bp->fatrec, dev));
  206. }
  207.  
  208. int readroo (dev)            /* read root directory */
  209. int dev;
  210. {
  211.    return (!Rwabs (0, rootbuf, bp->rdlen, bp->fatrec + bp->fsiz, dev));
  212. }
  213.  
  214. int readclu (cl, dev)            /* read cluster */
  215. int cl, dev;
  216. {
  217.    return (!Rwabs (0, clusbuf, bp->clsiz, (cl-2)*bp->clsiz+bp->datrec, dev));
  218. }
  219.  
  220. int freebuf ()                /* free memory for buffers */
  221. {
  222.    Mfree (rootbuf);
  223.    Mfree (fat1buf);
  224.    Mfree (fat2buf);
  225.    Mfree (clusbuf);
  226. }
  227.  
  228. int branch (devo, clus, key, inf)    /* recursive branch traverse */
  229. register int devo, clus, key;
  230. register GSINFO *inf;
  231. {
  232.    register FCB *fp;
  233.    register int fcount, fx;
  234.    int sclus, nclus, px;
  235.    if (clus != ROOT)
  236.    {
  237.       (*(fat2buf+clus))++;
  238.       if (!readclu (clus, devo))
  239.       {
  240.          if (inf)
  241.             inf->gs_fpath[0] = '\0';
  242.          return (0);
  243.       }
  244.       fp = (FCB *)clusbuf;
  245.       fcount = (bp->clsizb / sizeof(FCB)) - 1;
  246.    }
  247.    else
  248.    {
  249.       if (inf)
  250.          inf->gs_fpath[px = 0] = '\0';
  251.       fp = (FCB *)rootbuf;
  252.       fcount = ((bp->rdlen * bp->recsiz) / sizeof(FCB)) - 1;
  253.    }
  254.    fx = 0;
  255.    while (fx <= fcount)
  256.    {
  257.       if ((fp->f_name[0] != FN_FRE) && ((fp->f_name[0] & 0xff) != FN_DEL)
  258.          && (fp->f_name[0] != FN_DIR) && fp->f_clust)
  259.       {
  260.          swapb (&fp->f_clust, &sclus);
  261.          if (key == sclus)
  262.          {
  263.             inf->gs_dsect = ((clus != ROOT) ? (clus-2)*bp->clsiz+bp->datrec
  264.                : (bp->fatrec + bp->fsiz) + (fx / (bp->recsiz / sizeof(FCB))));
  265.             inf->gs_doff = (fx * sizeof(FCB)) % bp->recsiz;
  266.             addfn (&fp->f_name[0], &inf->gs_fpath[0]);
  267.             return (1);
  268.          }
  269.          if (fp->f_attrib == FA_SUB)
  270.          {
  271.             if (inf)
  272.                px = addfn (&fp->f_name[0], &inf->gs_fpath[0]);
  273.             if (branch (devo, sclus, key, inf))
  274.                return (1);
  275.             if (inf)
  276.                inf->gs_fpath[px] = '\0';
  277.             if (clus != ROOT)
  278.                if (!readclu (clus, devo))
  279.                {
  280.                   if (inf)
  281.                      inf->gs_fpath[0] = '\0';
  282.                   return (0);
  283.                }
  284.          }
  285.          else if (!key)
  286.             leaf (sclus);
  287.       }
  288.       if ((clus != ROOT) && (fx == fcount)) 
  289.       {
  290.          nclus = nextcl (clus);
  291.          if (!nclus || (nclus == EOFAT))
  292.             break;
  293.          if (*(fat2buf+nclus))
  294.          {
  295.             (*(fat2buf+nclus))++;
  296.             break;
  297.          }
  298.          clus = nclus;
  299.          (*(fat2buf+clus))++;
  300.          if (!readclu (clus, devo))
  301.          {
  302.             if (inf)
  303.                inf->gs_fpath[0] = '\0';
  304.                return (0);
  305.          }
  306.          fp = (FCB *)clusbuf, fx = 0;
  307.       }
  308.       else
  309.          fp++, fx++;
  310.    }
  311.    return (0);
  312. }
  313.  
  314. int leaf (clus)                /* linear leaf traverse */
  315. register int clus;
  316. {
  317.    register int nclus;
  318.    (*(fat2buf+clus))++;
  319.    nclus = nextcl (clus);
  320.    while (nclus && (nclus != EOFAT))
  321.    {
  322.       if (*(fat2buf+nclus))
  323.       {
  324.          (*(fat2buf+nclus))++;
  325.          break;
  326.       }
  327.       clus = nclus;
  328.       (*(fat2buf+clus))++;
  329.       nclus = nextcl (clus);
  330.    }
  331. }
  332.  
  333. int nextcl (cl)                /* next cluster in chain */
  334. register int cl;
  335. {
  336.    unsigned ncl;
  337.    if (bp->b_flags & BF_F16)
  338.    {
  339.       swapb (fat1buf+(cl*2), &ncl);
  340.       ncl = ((ncl >= 0xfff0) && (ncl <= 0xffff)) ? EOFAT : ncl;
  341.    }
  342.    else
  343.    {
  344.       swapb (fat1buf+(cl+(cl/2)), &ncl);
  345.       if (cl & 0x0001)
  346.          ncl >>= 4;
  347.       ncl &= 0x0fff;
  348.       ncl = ((ncl >= 0x0ff0) && (ncl <= 0x0fff)) ? EOFAT : ncl;
  349.    }
  350.    return (ncl);
  351. }
  352.  
  353. int addfn (src, dst)            /* add file name to path string */
  354. register char *src, *dst;
  355. {
  356.    register int old, i;
  357.    for (old = 0; *dst; dst++, old++);
  358.    *dst++ = '\\';
  359.    for (i = 0; i < 11; src++, i++)
  360.    {
  361.       if ((*src) && (*src != ' '))
  362.       {
  363.          if (i == 8)
  364.             *dst++ = '.';
  365.          *dst++ = *src;
  366.       }
  367.    }
  368.    *dst = '\0';
  369.    return (old);
  370. }
  371.  
  372. int bsearch (list, len, key)        /* binary search a la k&r */
  373. register int list[], len, key;
  374. {
  375.    register int low, mid, high;
  376.    low = 0;
  377.    high = len - 1;
  378.    while (low <= high)
  379.    {
  380.       mid = (low + high) / 2;
  381.       if (key < list[mid])
  382.          high = mid - 1;
  383.       else if (key > list[mid])
  384.          low = mid + 1;
  385.       else
  386.          return (1);
  387.    }
  388.    return (0);
  389. }
  390.  
  391. int swapb (from, to)            /* swap adjacent bytes */
  392. register char *from, *to;
  393. {
  394.    register char temp;
  395.    temp = *from++;
  396.    *to++ = *from;
  397.    *to = temp;
  398. }
  399.